{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Battery Electric Vehicle Charging\n",
    "\n",
    "In this example a battery electric vehicle (BEV) is driven 100 km in the morning and 100 km in the evening, to simulate commuting, and charged during the day by a solar panel at the driver's place of work. The size of the panel is computed by the optimisation.\n",
    "\n",
    "The BEV has a battery of size 100 kWh and an electricity consumption of 0.18 kWh/km.\n",
    "\n",
    "**NB:** this example will use units of kW and kWh, unlike the PyPSA defaults"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pypsa\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# use 24 hour period for consideration\n",
    "index = pd.date_range(\"2016-01-01 00:00\",\"2016-01-01 23:00\", freq=\"H\")\n",
    "\n",
    "# consumption pattern of BEV\n",
    "bev_usage = pd.Series([0.]*7 + [9.]*2 + [0.]*8 + [9.]*2 + [0.]*5, index)\n",
    "\n",
    "# solar PV panel generation per unit of capacity\n",
    "pv_pu = pd.Series([0.]*7 + [0.2,0.4,0.6,0.75,0.85,0.9,0.85,0.75,0.6,0.4,0.2,0.1] + [0.]*5, index)\n",
    "\n",
    "# availability of charging - i.e. only when parked at office\n",
    "charger_p_max_pu = pd.Series(0, index=index)\n",
    "charger_p_max_pu[\"2016-01-01 09:00\":\"2016-01-01 16:00\"] = 1."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.concat({'BEV': bev_usage, 'PV': pv_pu, 'Charger': charger_p_max_pu}, axis=1)\n",
    "df.plot.area(subplots=True, figsize=(10,7))\n",
    "plt.tight_layout()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Initialize the network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network = pypsa.Network()\n",
    "network.set_snapshots(index)\n",
    "\n",
    "network.add(\"Bus\",\n",
    "            \"place of work\",\n",
    "            carrier=\"AC\")\n",
    "\n",
    "network.add(\"Bus\",\n",
    "            \"battery\",\n",
    "            carrier=\"Li-ion\")\n",
    "\n",
    "network.add(\"Generator\",\n",
    "            \"PV panel\",\n",
    "            bus=\"place of work\",\n",
    "            p_nom_extendable=True,\n",
    "            p_max_pu=pv_pu,\n",
    "            capital_cost=1000.)\n",
    "\n",
    "network.add(\"Load\",\n",
    "            \"driving\",\n",
    "            bus=\"battery\",\n",
    "            p_set=bev_usage)\n",
    "\n",
    "network.add(\"Link\",\n",
    "            \"charger\",\n",
    "            bus0=\"place of work\",\n",
    "            bus1=\"battery\",\n",
    "            p_nom=120,  #super-charger with 120 kW\n",
    "            p_max_pu=charger_p_max_pu,\n",
    "            efficiency=0.9)    \n",
    "\n",
    "\n",
    "network.add(\"Store\",\n",
    "            \"battery storage\",\n",
    "            bus=\"battery\",\n",
    "            e_cyclic=True,\n",
    "            e_nom=100.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network.lopf()\n",
    "print(\"Objective:\",network.objective)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The optimal panel size in kW is"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network.generators.p_nom_opt[\"PV panel\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network.generators_t.p.plot.area(figsize = (9,4))\n",
    "plt.tight_layout()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame({attr: network.stores_t[attr][\"battery storage\"] for attr in [\"p\",\"e\"]})\n",
    "df.plot(grid=True, figsize = (10,5))\n",
    "plt.legend(labels=['Energy output', 'State of charge'])\n",
    "plt.tight_layout()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The losses in kWh per pay are:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network.generators_t.p.loc[:,\"PV panel\"].sum() - network.loads_t.p.loc[:,\"driving\"].sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network.links_t.p0.plot.area(figsize = (9,5))\n",
    "plt.tight_layout()"
   ]
  }
 ],
 "metadata": {
  "@webio": {
   "lastCommId": null,
   "lastKernelId": null
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
